
#ifndef TYPEDFILE_H_
#define TYPEDFILE_H_

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "xexception.h"

template<typename T>
class TypedFile
	{
	private:
	    /* used to get the size of the file */
	    struct stat buf;
	    /* genome fasta file file descriptor */
	    int fd;
	    /* the mmap (memory mapped) pointer */
	    char *mapptr;
	    TypedFile(const TypedFile<T>& cp)
		{
		}
	public:
	    TypedFile(const char* filename)
		{
		/* get the whole size of the fasta file */
		  if(::stat(filename, &buf)!=0)
			{
			THROW("Cannot stat "<< filename);
			}

		  /* open the fasta file */
		  fd = open(filename, O_RDONLY);
		   if (fd == -1)
			{
			THROW("Error opening file for reading");
		        }
		  /* open a memory mapped file associated to this fasta file descriptor */
		  mapptr = (char*)mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
		  if (mapptr == MAP_FAILED)
			{
		        close(fd);
		        THROW("Error mmapping the file");
			}
		}
	    virtual ~TypedFile()
		{
		/* close memory mapped map */
		if(mapptr!=NULL && munmap(mapptr,buf.st_size) == -1)
			{
			perror("Error un-mmapping the file");
			}
		 /* dispose fasta file descriptor */
		if(fd!=-1) close(fd);
		}

	    T* get(long index,T* value)
		{
		std::memcpy(value,&mapptr[index*sizeof(T)],sizeof(T));
		return value;
		}

	    T get(long index)
		{
		T t;
		get(index,&t);
		return t;
		}

	    T operator[](long index)
		{
		return get(index);
		}

	    long size() const
		{
		return buf.st_size/sizeof(T);
		}
	};

#endif

